﻿using System;
using System.Collections.Generic;
using System.Linq;
using Observers;

namespace Domain.Services
{
    public interface IObservable
    {
        void Attach(IObserver observer);

        void Detach(IObserver observer);

        void Notify();
    }

    public interface IOrderService
    {
        void Submit(Order order);
        Order LastOrder { get; }
    }

    public class OrderService : IOrderService, IObservable
    {
        private readonly IDictionary<string, IObserver> observers = new Dictionary<string, IObserver>();
        private readonly IList<Order> orders = new List<Order>();
        private static int currentOrderNumber = 1000;

        public void Attach(IObserver observer)
        {
            observers.Add(observer.GetType().Name, observer);
        }

        public void Detach(IObserver observer)
        {
            observers.Remove(observer.GetType().Name);
        }

        public void Notify()
        {
            foreach (var observer in observers.Values)
            {
                observer.Subject = this;
                observer.Update();
            }
        }

        public void Submit(Order order)
        {
            // Here is where we send the Order object to wherever it is going...
            order.OrderNumber = GetNextOrderNumber();
            order.HasErrors = ErrorsFoundIn(order);
            orders.Add(order);
            Console.WriteLine("Order #{0} Submitted @ {1}\n{2}\n=======================================================\n", 
                order.OrderNumber, DateTime.Now, order.Customer);

            Notify();
        }

        private static bool ErrorsFoundIn(Order order)
        {
            return (((int) order.OrderAmount)%order.Customer.Length == 0); // I know... this is dumb
        }

        private static int GetNextOrderNumber()
        {
            return ++currentOrderNumber;
        }

        public Order LastOrder
        {
            get { return orders.Last(); }
        }

        /// <summary>
        /// Gets recent orders.
        /// </summary>
        /// <param name="count">The count.</param>
        /// <returns>The number of orders to return.</returns>
        public IEnumerable<Order> RecentOrders(int count)
        {
            if(count > 500)
                throw new InvalidOperationException("More than 500 orders is just too many. Refine your query a little better please! :)");

            return (orders.OrderBy(o => o.DateOrdered).Reverse()).Take(count);
        }
    }
}
